package cn.ecut.dzy.cf;

import java.util.concurrent.*;

/**
 * @program: juc
 * @description:
 * @author: DingZhenYun
 * @create: 2021-10-19 20:05
 **/

public class CompletableFutureAPIDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // m1();
        m2();
        System.out.println("-------m3--");
        m3();
        System.out.println("-------m4--");
        m4();
        System.out.println("-------m5--");
        m5();
        System.out.println("-------m6--");
        m6();

    }

    /**
     * 获得结果和触发计算
     *
     * @throws InterruptedException
     * @throws ExecutionException
     */
    public static void m1() throws ExecutionException, InterruptedException {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 1L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //暂停几秒钟线程
            //暂停几秒钟线程
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1;
        }, threadPoolExecutor);
        //System.out.println(future.get(2L,TimeUnit.SECONDS));//过时不候
        //暂停几秒钟线程
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //System.out.println(integerCompletableFuture.getNow(9999));//备胎
        //complete打断
        System.out.println(integerCompletableFuture.complete(-44) + "\t" + integerCompletableFuture.get());
        threadPoolExecutor.shutdown();
    }

    /**
     * 对计算结果进行处理
     */
    public static void m2() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 1L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
//        由于存在依赖关系(当前步错，不走下一步)，当前步骤有异常的话就叫停。
        //        CompletableFuture.supplyAsync(()->{
//            return 1;
//        },threadPoolExecutor).thenApply(f->{
//            System.out.println("-----1");
////            int i=10/0;
//            return f+2;
//        }).thenApply(f->{
//            System.out.println("-----2");
//            return f+3;
//        }).whenComplete((v,e)->{
//            if(e==null){
//                System.out.println("---result:"+v);
//            }
//        }).exceptionally(e->{
//            e.printStackTrace();
//            return null;
//        }).join();
        CompletableFuture.supplyAsync(() -> {
            return 1;
        }, threadPoolExecutor).handle((f, e) -> {
            System.out.println("-----1");
            //int i=10/0;
            return f + 2;
        }).handle((f, e) -> {
            System.out.println("-----2");
            return f + 3;
        }).whenComplete((v, e) -> {
            if (e == null) {
                System.out.println("---result:" + v);
            }
        }).exceptionally(e -> {
            e.printStackTrace();
            return null;
        }).join();
        threadPoolExecutor.shutdown();
    }


    /**
     * 对计算结果进行消费
     */
    public static void m3() {
        CompletableFuture.supplyAsync(() -> {
            return 1;
        }).thenApply(f -> {
            return f + 2;
        }).thenApply(f -> {
            return f + 3;
        }).thenAccept(r -> {
            System.out.println(r);
        });


        //任务 A 执行完执行 B，并且 B 不需要 A 的结果
        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenRun(() -> {
        }).join());

        //任务 A 执行完执行 B，B 需要 A 的结果，但是任务 B 无返回值
        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenAccept(resultA -> {
        }).join());

        //任务 A 执行完执行 B，B 需要 A 的结果，同时任务 B 有返回值
        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenApply(resultA -> resultA + " resultB").join());
    }

    /**
     * 对计算速度进行选用
     */
    public static void m4() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 1L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        System.out.println(CompletableFuture.supplyAsync(() -> {
                    //暂停几秒钟线程
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return 1;
                }, threadPoolExecutor).applyToEither(CompletableFuture.supplyAsync(() -> {
                    //暂停几秒钟线程
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return 1;
                }, threadPoolExecutor), r -> {
                    return r;
                }).join()
        );
    }

    /**
     * thenCombine
     * thenCombine会在两个任务都执行完成后，把两个任务的结果合并。
     * 注意：
     * 两个任务中只要有一个执行异常，则将该异常信息作为指定任务的执行结果。
     * 两个任务是并行执行的，它们之间并没有先后依赖顺序。
     */
    public static void m5() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 1L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        Integer join = CompletableFuture.supplyAsync(() -> {
            System.out.println("m5--111");
            return 10;
        }, threadPoolExecutor).thenCombine(CompletableFuture.supplyAsync(() -> {
            System.out.println("m5--222");
            return 20;
        }, threadPoolExecutor), (r1, r2) -> {
            System.out.println("m5--333");
            return r1 + r2;
        }).thenCombine(CompletableFuture.supplyAsync(()->{
            System.out.println("m5--444");
            //int a = 1 / 0;//出了异常就报错
            return 100;
        },threadPoolExecutor),(r1, r2) -> {
            System.out.println("m5--555");

            return r1 + r2;
        }).join();
        System.out.println(join);
        threadPoolExecutor.shutdown();
    }

    /**
     * thenCompose 可以用于组合多个CompletableFuture，将前一个任务的返回结果作为下一个任务的参数，它们之间存在着先后顺序。
     * 用来连接两个CompletableFuture，是生成一个新的CompletableFuture。
     */
    public static void m6() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20, 1L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        Integer join = CompletableFuture.supplyAsync(() -> {
            return 10;
        }, threadPoolExecutor).thenCompose(f -> {
            return CompletableFuture.supplyAsync(() -> {
                return f * 10 + 1;
            }, threadPoolExecutor);
        }).join();
        System.out.println(join);
        threadPoolExecutor.shutdown();
}
}
